12 进程的创建
复制结构
dup_task_struct:
- 调用 alloc_task_struct_node 分配一个 task_struct 结构;
- 调用 alloc_thread_stack_node 创建内核栈,这里面调用 __vmalloc_node_range 分配一个连续的 THREAD_SIZE 的内存空间,赋值给 task_struct 的 void *stack 成员变量;
- 调用 arch_dup_task_struct(struct task_struct *dst, struct task_struct *src),将 task_struct 进行复制,即调用 memcpy;
- 调用 setup_thread_stack 设置 thread_info。
copy_creds 权限相关:
- 调用 prepare_creds,准备一个新的 struct cred *new;
- 接着 p->cred = p->real_cred = get_cred(new),将新进程的权限指向新的 cred。
copy_process 设置调度相关:
- 调用 __sched_fork,将 on_rq 设为 0,初始化 sched_entity,将 exec_start、sum_exec_runtime、prev_sum_exec_runtime、vruntime 都设为 0;
- 设置进程的状态 p->state = TASK_NEW;
- 初始化优先级 prio、normal_prio、static_prio;
- 设置调度类,如果是普通进程,就设置为 p->sched_class = &fair_sched_class;
- 调用调度类的 task_fork 函数,对于 CFS 来讲,就是调用 task_fork_fair。
copy_process 初始化与文件和文件系统相关的变量:
copy_process 初始化与信号相关的变量:
copy_process 复制进程内存空间:
唤醒新进程
wake_up_new_task:
- state = TASK_RUNNING; activate 用调度类将当前子进程入队列
- enqueue_entiry 中会调用 update_curr 更新运行统计量, 再加入队列
- 调用 check_preempt_curr 看是否能抢占, 若 task_fork_fair 中已设置 sysctl_sched_child_runs_first, 直接返回, 否则进一步比较并调用 resched_curr 做抢占标记
- 若父进程被标记会被抢占, 则系统调用 fork 返回过程会调度子进程